package com.zhou.common.mybatis.template.shiro.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhou.common.mybatis.template.shiro.config.ShiroConstants;
import com.zhou.common.mybatis.template.shiro.entity.SysUserOnline;
import com.zhou.common.mybatis.template.shiro.enums.OnlineStatus;
import com.zhou.common.mybatis.template.shiro.mapper.SysUserOnlineMapper;
import com.zhou.common.mybatis.template.shiro.service.ISysUserOnlineService;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Date;
import java.util.Deque;
import java.util.List;

/**
 * <p>
 * 在线用户记录 服务实现类
 * </p>
 *
 * @author zxf
 * @since 2023-02-20
 */
@Service
public class SysUserOnlineServiceImpl extends ServiceImpl<SysUserOnlineMapper, SysUserOnline> implements ISysUserOnlineService {


    @Autowired
    private CacheManager cacheManager;

    @Override
    public SysUserOnline selectOnlineById(String sessionId) {
        SysUserOnline sysUserOnline= lambdaQuery().eq(SysUserOnline::getId, sessionId).one();
        return sysUserOnline;
    }

    @Override
    public void deleteOnlineById(String sessionId) {
        LambdaUpdateWrapper<SysUserOnline> eq = Wrappers.<SysUserOnline>lambdaUpdate().eq(SysUserOnline::getId, sessionId)
                .set(SysUserOnline::getStatus, OnlineStatus.off_line);
        update(eq);
    }

    @Override
    public void batchDeleteOnline(List<String> sessions) {
        LambdaUpdateWrapper<SysUserOnline> eq = Wrappers.<SysUserOnline>lambdaUpdate()
                .in(SysUserOnline::getId, sessions)
                .set(SysUserOnline::getStatus, OnlineStatus.off_line);
       update(eq);
    }

    @Override
    public void saveOnline(SysUserOnline online) {
        LambdaQueryChainWrapper<SysUserOnline> eq = lambdaQuery().eq(SysUserOnline::getId, online.getId());
        int count = eq.count();
        if (count>0){
            updateById(online);
        }else {
            save(online);
        }
    }

    @Override
    public List<SysUserOnline> selectUserOnlineList(SysUserOnline userOnline) {
        List<SysUserOnline> sysUserOnlines = baseMapper.selectUserOnlineList(userOnline);
        return sysUserOnlines;
    }

    @Override
    public void forceLogout(String sessionId) {
        LambdaUpdateWrapper<SysUserOnline> eq = Wrappers.<SysUserOnline>lambdaUpdate().eq(SysUserOnline::getId, sessionId);
        remove(eq);
    }



    @Override
    public void removeUserCache(String loginName, String sessionId) {
        Cache<String, Deque<Serializable>> cache= cacheManager.getCache(ShiroConstants.SYS_USERCACHE);
        Deque<Serializable> deque = cache.get(loginName);
        if (deque == null) {
            return;
        }
        if (deque.contains(sessionId) ) {
            deque.remove(sessionId);
            cache.put(loginName, deque);
        }
    }

    @Override
    public List<SysUserOnline> selectOnlineByExpired(Date expiredDate) {
        //		WHERE o.last_access_time <![CDATA[ <= ]]> #{lastAccessTime} ORDER BY o.last_access_time ASC
        LambdaQueryWrapper<SysUserOnline> queryWrapper = Wrappers.<SysUserOnline>lambdaQuery()
                .le(SysUserOnline::getLastAccessTime, expiredDate)
                .eq(SysUserOnline::getStatus, OnlineStatus.on_line)
                .orderByAsc(SysUserOnline::getLastAccessTime);
        return baseMapper.selectList(queryWrapper);
    }
}
